home *** CD-ROM | disk | FTP | other *** search
/ Java Primer Plus / Java Primer Plus (Waite Group Proess)(1996).iso / java_Win / demo / GraphLayout / GraphPanel.class (.txt) < prev    next >
Encoding:
Java Class File  |  1995-10-12  |  6.9 KB  |  264 lines

  1. import java.awt.Color;
  2. import java.awt.Component;
  3. import java.awt.Dimension;
  4. import java.awt.Event;
  5. import java.awt.FontMetrics;
  6. import java.awt.Graphics;
  7. import java.awt.Image;
  8. import java.awt.Panel;
  9. import java.awt.image.ImageObserver;
  10.  
  11. class GraphPanel extends Panel implements Runnable {
  12.    Graph graph;
  13.    int nnodes;
  14.    Node[] nodes = new Node[100];
  15.    int nedges;
  16.    Edge[] edges = new Edge[200];
  17.    Thread relaxer;
  18.    boolean stress;
  19.    boolean random;
  20.    Node pick;
  21.    boolean pickfixed;
  22.    Image offscreen;
  23.    Dimension offscreensize;
  24.    Graphics offgraphics;
  25.    final Color fixedColor;
  26.    final Color selectColor;
  27.    final Color edgeColor;
  28.    final Color nodeColor;
  29.    final Color stressColor;
  30.    final Color arcColor1;
  31.    final Color arcColor2;
  32.    final Color arcColor3;
  33.  
  34.    GraphPanel(Graph graph) {
  35.       this.fixedColor = Color.red;
  36.       this.selectColor = Color.pink;
  37.       this.edgeColor = Color.black;
  38.       this.nodeColor = new Color(250, 220, 100);
  39.       this.stressColor = Color.gray;
  40.       this.arcColor1 = Color.black;
  41.       this.arcColor2 = Color.pink;
  42.       this.arcColor3 = Color.red;
  43.       this.graph = graph;
  44.    }
  45.  
  46.    int findNode(String lbl) {
  47.       for(int i = 0; i < this.nnodes; ++i) {
  48.          if (this.nodes[i].lbl.equals(lbl)) {
  49.             return i;
  50.          }
  51.       }
  52.  
  53.       return this.addNode(lbl);
  54.    }
  55.  
  56.    int addNode(String lbl) {
  57.       Node n = new Node();
  58.       n.x = (double)10.0F + (double)380.0F * Math.random();
  59.       n.y = (double)10.0F + (double)380.0F * Math.random();
  60.       n.lbl = lbl;
  61.       this.nodes[this.nnodes] = n;
  62.       return this.nnodes++;
  63.    }
  64.  
  65.    void addEdge(String from, String to, int len) {
  66.       Edge e = new Edge();
  67.       e.from = this.findNode(from);
  68.       e.to = this.findNode(to);
  69.       e.len = (double)len;
  70.       this.edges[this.nedges++] = e;
  71.    }
  72.  
  73.    public void run() {
  74.       while(true) {
  75.          this.relax();
  76.          if (this.random && Math.random() < 0.03) {
  77.             Node n = this.nodes[(int)(Math.random() * (double)this.nnodes)];
  78.             if (!n.fixed) {
  79.                n.x += (double)100.0F * Math.random() - (double)50.0F;
  80.                n.y += (double)100.0F * Math.random() - (double)50.0F;
  81.             }
  82.  
  83.             this.graph.play(this.graph.getCodeBase(), "audio/drip.au");
  84.          }
  85.  
  86.          try {
  87.             Thread.sleep(100L);
  88.          } catch (InterruptedException var2) {
  89.             return;
  90.          }
  91.       }
  92.    }
  93.  
  94.    synchronized void relax() {
  95.       for(int i = 0; i < this.nedges; ++i) {
  96.          Edge e = this.edges[i];
  97.          double vx = this.nodes[e.to].x - this.nodes[e.from].x;
  98.          double vy = this.nodes[e.to].y - this.nodes[e.from].y;
  99.          double len = Math.sqrt(vx * vx + vy * vy);
  100.          double f = (this.edges[i].len - len) / (len * (double)3.0F);
  101.          double dx = f * vx;
  102.          double dy = f * vy;
  103.          Node var10000 = this.nodes[e.to];
  104.          var10000.dx += dx;
  105.          var10000 = this.nodes[e.to];
  106.          var10000.dy += dy;
  107.          var10000 = this.nodes[e.from];
  108.          var10000.dx += -dx;
  109.          var10000 = this.nodes[e.from];
  110.          var10000.dy += -dy;
  111.       }
  112.  
  113.       for(int i = 0; i < this.nnodes; ++i) {
  114.          Node n1 = this.nodes[i];
  115.          double dx = (double)0.0F;
  116.          double dy = (double)0.0F;
  117.  
  118.          for(int j = 0; j < this.nnodes; ++j) {
  119.             if (i != j) {
  120.                Node n2 = this.nodes[j];
  121.                double vx = n1.x - n2.x;
  122.                double vy = n1.y - n2.y;
  123.                double len = vx * vx + vy * vy;
  124.                if (len == (double)0.0F) {
  125.                   dx += Math.random();
  126.                   dy += Math.random();
  127.                } else if (len < (double)10000.0F) {
  128.                   dx += vx / len;
  129.                   dy += vy / len;
  130.                }
  131.             }
  132.          }
  133.  
  134.          double dlen = dx * dx + dy * dy;
  135.          if (dlen > (double)0.0F) {
  136.             dlen = Math.sqrt(dlen) / (double)2.0F;
  137.             n1.dx += dx / dlen;
  138.             n1.dy += dy / dlen;
  139.          }
  140.       }
  141.  
  142.       Dimension d = ((Component)this).size();
  143.  
  144.       for(int i = 0; i < this.nnodes; ++i) {
  145.          Node n = this.nodes[i];
  146.          if (!n.fixed) {
  147.             n.x += Math.max((double)-5.0F, Math.min((double)5.0F, n.dx));
  148.             n.y += Math.max((double)-5.0F, Math.min((double)5.0F, n.dy));
  149.             if (n.x < (double)0.0F) {
  150.                n.x = (double)0.0F;
  151.             } else if (n.x > (double)d.width) {
  152.                n.x = (double)d.width;
  153.             }
  154.  
  155.             if (n.y < (double)0.0F) {
  156.                n.y = (double)0.0F;
  157.             } else if (n.y > (double)d.height) {
  158.                n.y = (double)d.height;
  159.             }
  160.          }
  161.  
  162.          n.dx /= (double)2.0F;
  163.          n.dy /= (double)2.0F;
  164.       }
  165.  
  166.       ((Component)this).repaint();
  167.    }
  168.  
  169.    public void paintNode(Graphics g, Node n, FontMetrics fm) {
  170.       int x = (int)n.x;
  171.       int y = (int)n.y;
  172.       g.setColor(n == this.pick ? this.selectColor : (n.fixed ? this.fixedColor : this.nodeColor));
  173.       int w = fm.stringWidth(n.lbl) + 10;
  174.       int h = fm.getHeight() + 4;
  175.       g.fillRect(x - w / 2, y - h / 2, w, h);
  176.       g.setColor(Color.black);
  177.       g.drawRect(x - w / 2, y - h / 2, w - 1, h - 1);
  178.       g.drawString(n.lbl, x - (w - 10) / 2, y - (h - 4) / 2 + fm.getAscent());
  179.    }
  180.  
  181.    public synchronized void update(Graphics g) {
  182.       Dimension d = ((Component)this).size();
  183.       if (this.offscreen == null || d.width != this.offscreensize.width || d.height != this.offscreensize.height) {
  184.          this.offscreen = ((Component)this).createImage(d.width, d.height);
  185.          this.offscreensize = d;
  186.          this.offgraphics = this.offscreen.getGraphics();
  187.          this.offgraphics.setFont(((Component)this).getFont());
  188.       }
  189.  
  190.       this.offgraphics.setColor(((Component)this).getBackground());
  191.       this.offgraphics.fillRect(0, 0, d.width, d.height);
  192.  
  193.       for(int i = 0; i < this.nedges; ++i) {
  194.          Edge e = this.edges[i];
  195.          int x1 = (int)this.nodes[e.from].x;
  196.          int y1 = (int)this.nodes[e.from].y;
  197.          int x2 = (int)this.nodes[e.to].x;
  198.          int y2 = (int)this.nodes[e.to].y;
  199.          int len = (int)Math.abs(Math.sqrt((double)((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))) - e.len);
  200.          this.offgraphics.setColor(len < 10 ? this.arcColor1 : (len < 20 ? this.arcColor2 : this.arcColor3));
  201.          this.offgraphics.drawLine(x1, y1, x2, y2);
  202.          if (this.stress) {
  203.             String lbl = String.valueOf(len);
  204.             this.offgraphics.setColor(this.stressColor);
  205.             this.offgraphics.drawString(lbl, x1 + (x2 - x1) / 2, y1 + (y2 - y1) / 2);
  206.             this.offgraphics.setColor(this.edgeColor);
  207.          }
  208.       }
  209.  
  210.       FontMetrics fm = this.offgraphics.getFontMetrics();
  211.  
  212.       for(int i = 0; i < this.nnodes; ++i) {
  213.          this.paintNode(this.offgraphics, this.nodes[i], fm);
  214.       }
  215.  
  216.       g.drawImage(this.offscreen, 0, 0, (ImageObserver)null);
  217.    }
  218.  
  219.    public synchronized boolean mouseDown(Event evt, int x, int y) {
  220.       double bestdist = Double.MAX_VALUE;
  221.  
  222.       for(int i = 0; i < this.nnodes; ++i) {
  223.          Node n = this.nodes[i];
  224.          double dist = (n.x - (double)x) * (n.x - (double)x) + (n.y - (double)y) * (n.y - (double)y);
  225.          if (dist < bestdist) {
  226.             this.pick = n;
  227.             bestdist = dist;
  228.          }
  229.       }
  230.  
  231.       this.pickfixed = this.pick.fixed;
  232.       this.pick.fixed = true;
  233.       this.pick.x = (double)x;
  234.       this.pick.y = (double)y;
  235.       ((Component)this).repaint();
  236.       return true;
  237.    }
  238.  
  239.    public synchronized boolean mouseDrag(Event evt, int x, int y) {
  240.       this.pick.x = (double)x;
  241.       this.pick.y = (double)y;
  242.       ((Component)this).repaint();
  243.       return true;
  244.    }
  245.  
  246.    public synchronized boolean mouseUp(Event evt, int x, int y) {
  247.       this.pick.x = (double)x;
  248.       this.pick.y = (double)y;
  249.       this.pick.fixed = this.pickfixed;
  250.       this.pick = null;
  251.       ((Component)this).repaint();
  252.       return true;
  253.    }
  254.  
  255.    public void start() {
  256.       this.relaxer = new Thread(this);
  257.       this.relaxer.start();
  258.    }
  259.  
  260.    public void stop() {
  261.       this.relaxer.stop();
  262.    }
  263. }
  264.